package com.gitee.feizns.quickstart.mybatis.plus.spring.boot.autoconfigure;

import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gitee.feizns.quickstart.mybatis.plus.handler.type.JacksonGenericTypeHandler;
import com.gitee.feizns.quickstart.mybatis.plus.injector.sql.QuickstartMybatisPlusSqlInjector;
import com.gitee.feizns.quickstart.mybatis.plus.plugins.inner.autofill.AutoFillAnnotationInnerInterceptor;
import com.gitee.feizns.quickstart.mybatis.plus.plugins.inner.autofill.annotation.AutoFill;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

/**
 * mybatis plus 配置类
 * <a href="https://baomidou.com/pages/24112f/#%E7%89%B9%E6%80%A7">mybatis plus官网</a>
 * @author feizns
 * @since 2022/11/25
 */
@AllArgsConstructor
@Configuration
@EnableConfigurationProperties(QuickstartMybatisPlusProperties.class)
public class QuickstartMybatisPlusConfiguration implements ApplicationListener<ContextRefreshedEvent> {

    /**
     * {@link QuickstartMybatisPlusProperties}
     */
    private final QuickstartMybatisPlusProperties properties;

    /**
     * 快速入门mybatis + sql注入器
     * @return {@link QuickstartMybatisPlusSqlInjector}
     */
    @Bean
    @ConditionalOnMissingBean
    public QuickstartMybatisPlusSqlInjector quickstartMybatisPlusSqlInjector() {
        return new QuickstartMybatisPlusSqlInjector();
    }

    /**
     * mybatis plus 插件
     * @return {@link MybatisPlusInterceptor}
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(List<InnerInterceptor> innerInterceptors) {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.setInterceptors(innerInterceptors);
        return interceptor;
    }

    /**
     * mybatis plus 分页插件
     * @return {@link PaginationInnerInterceptor}
     */
    @Bean
    @ConditionalOnMissingBean
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        paginationInnerInterceptor.setMaxLimit((long) properties.getPageMaxLimit());
        return paginationInnerInterceptor;
    }

    /**
     * 可以配置雪花Id的生成机器编号
     * @return {@link IdentifierGenerator}
     */
    @Bean
    @ConditionalOnMissingBean
    public IdentifierGenerator identifierGenerator() throws UnknownHostException {
        return new DefaultIdentifierGenerator(InetAddress.getLocalHost());
    }

    /**
     * 乐观锁拦截器
     * @return {@link OptimisticLockerInnerInterceptor}
     */
    @Bean
    @ConditionalOnProperty(prefix = "quickstart.mybatis.plus", name = "optimistic-locker-inner-interceptor-enabled", havingValue = "true")
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
        return new OptimisticLockerInnerInterceptor();
    }

    /**
     * 阻止攻击内部拦截器（防全表删除插件注册）
     * @return {@link BlockAttackInnerInterceptor}
     */
    @Bean
    @ConditionalOnProperty(prefix = "quickstart.mybatis.plus", name = "block-attack-inner-interceptor-enabled", matchIfMissing = true)
    public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
        return new BlockAttackInnerInterceptor();
    }

    /**
     * 自动填充注解处理器{@link AutoFill}
     * @return {@link AutoFillAnnotationInnerInterceptor}
     */
    @Bean
    public AutoFillAnnotationInnerInterceptor autoFillAnnotationMetaObjectHandler() {
        return new AutoFillAnnotationInnerInterceptor();
    }

    /**
     * 应用程序事件时
     * @param event 事件
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ObjectMapper objectMapper = event.getApplicationContext().getBean(ObjectMapper.class);
        JacksonTypeHandler.setObjectMapper(objectMapper);
        JacksonGenericTypeHandler.setObjectMapper(objectMapper);
    }

}
